home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / util / pack / xpk_Source.lha / xpk_Source / shell / xBench.c < prev    next >
C/C++ Source or Header  |  1998-11-09  |  13KB  |  560 lines

  1. #define NAME        "xBench"
  2. #define DISTRIBUTION    "(Freeware) "
  3. #define VERSION        "2"
  4. #define REVISION    "9"
  5.  
  6. /* Programmheader
  7.  
  8.         Name:           xBench
  9.         Author:         SDI (before 1.1 Urban Dominik Müller)
  10.         Distribution:   PD
  11.         Description:    xpk benchmark utility
  12.         Compileropts:   -gM
  13.         Linkeropts:     -l xpkmaster amiga -gsi
  14.  
  15.  1.1   29.11.96 : added version string
  16.  1.2   20.12.96 : added output telling the caller mechanism
  17.  2.0   31.03.97 : now OS 2.0 and up only, rewritten, now an utility to
  18.         allow users making benchmarks
  19.  2.1   01.04.97 : fixed some errors
  20.  2.2   23.04.97 : fixed time calculation
  21.  2.3   10.05.97 : added ALL flag, use with care!
  22.  2.4   08.06.97 : added forgotten TAG_DONE
  23.  2.5   20.06.97 : added Pattern Matching
  24.  2.6   10.10.97 : changed output style to prevent errors on large files
  25.  2.7   24.03.98 : added third buffer for source buffer check
  26.  2.8   19.07.98 : moved uncrunched length to top line for better output
  27.  2.9   24.08.98 : added logfile support
  28. */
  29.  
  30. #include <proto/dos.h>
  31. #include <proto/timer.h>
  32. #include <proto/xpkmaster.h>
  33. #include <proto/exec.h>
  34. #include <exec/memory.h>
  35. #include <exec/devices.h>
  36. #include "SDI_defines.h"
  37. #define SDI_TO_ANSI
  38. #include "SDI_ASM_STD_protos.h"
  39.  
  40. /* METHOD's are:
  41.  <mode - upper case, 4 chars>[.<mode - dec number>]
  42. */
  43.  
  44. #define PARAMS  "FILENAME/A,PASSWORD/K,METHOD/M,TEST/S,ALL/S,SAVE/K,"    \
  45.         "LOG=LOGFILE/K"
  46. #define HEADER  "File '%s' with a size of %ld bytes.\n" \
  47.         "Type  Num Version P    CSize     CTime      CSpd     UTime      USpd  Rate\n"
  48. #define DATATXT "%s: %3ld %2ld.%ld%s %s %8ld %6ld.%02ld %9ld %6ld.%02ld %9ld %3ld.%ld\n"
  49. #define SIZEERR "%s: FileSize false after decrunching %ld != %ld\n"
  50. #define BUFERR  "%s: Decrunched buffer different to source!\n"
  51. #define SRCERR  "%s: Source buffer destroyed!\n"
  52.  
  53. struct Args {
  54.   STRPTR        filename;
  55.   STRPTR        password;
  56.   STRPTR *      method;
  57.   ULONG        test;
  58.   ULONG        all;
  59.   STRPTR    save;
  60.   STRPTR    logfile;
  61. };
  62.  
  63. struct TestData {
  64.   STRPTR    sbuf;
  65.   STRPTR        cbuf;
  66.   ULONG        sbufsize;
  67.   STRPTR    pbuf;
  68.   ULONG        pbufsize;
  69.   STRPTR    ubuf;
  70.   ULONG        ubufsize;
  71.   STRPTR    password;
  72.   ULONG        test;
  73.   ULONG        all;
  74.   BPTR        logfh;
  75.   STRPTR    save;
  76.   struct FileInfoBlock *fib;
  77.   struct XpkPackerInfo *pinfo;
  78.   struct XpkMode *minfo;
  79. };
  80.  
  81. struct BenchData {
  82.   STRPTR    method;
  83.   ULONG        mode;
  84.   ULONG        version;
  85.   ULONG        revision;
  86.   STRPTR    pad;
  87.   STRPTR    password;
  88.   ULONG        CSize;
  89.   ULONG        CTime;
  90.   ULONG        CTime100;
  91.   ULONG        CSpd;
  92.   ULONG        UTime;
  93.   ULONG        UTime100;
  94.   ULONG        USpd;
  95.   ULONG        Rate;
  96.   ULONG        Rate10;
  97. };
  98.  
  99. struct DosLibrary *     DOSBase;
  100. struct ExecBase *    SysBase;
  101. struct Library *        XpkBase;
  102. struct Device *     TimerBase;
  103.  
  104. ULONG DoIt(STRPTR name, struct TestData *tdat, STRPTR *method);
  105. LONG GetPackData(struct BenchData *b, struct TestData *t, STRPTR pwd);
  106. void DoTest(struct TestData *data, STRPTR method, ULONG mode);
  107. void ScanMethods(struct TestData *data, STRPTR method);
  108. void PrintTxt(BPTR logfh, STRPTR txt, ...);
  109. void VPrintTxt(BPTR logfh, STRPTR txt, APTR args);
  110. void PrintErr(BPTR logfh, ULONG err, STRPTR method);
  111. void ScanPackers(struct TestData *data);
  112.  
  113. #define PATHNAME_SIZE 256
  114.  
  115. ULONG start(void) /* not named main, to get error with startup code ! */
  116. {
  117.  ULONG                  error   = RETURN_FAIL;
  118.  struct DosLibrary *    dosbase;
  119.  struct Process *       task;
  120.  
  121.  SysBase = (*((struct ExecBase **) 4));
  122.  /* test for WB and reply startup-message */
  123.  if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  124.  {
  125.   WaitPort(&task->pr_MsgPort);
  126.   Forbid();
  127.   ReplyMsg(GetMsg(&task->pr_MsgPort));
  128.   return RETURN_FAIL;
  129.  }
  130.  
  131.  if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  132.  {
  133.   struct Library *xpkbase;
  134.  
  135.   DOSBase = dosbase; /* set global base */
  136.   if((xpkbase = OpenLibrary("xpkmaster.library", 4)))
  137.   {
  138.    struct RDArgs *rda;
  139.    struct Args args;
  140.    
  141.    memset(&args, 0, sizeof(struct Args));
  142.  
  143.    XpkBase = xpkbase;
  144.    if((rda = ReadArgs(PARAMS, (LONG *) &args, 0)))
  145.    {
  146.     struct FileInfoBlock *fib;
  147.  
  148.     if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
  149.     {
  150.      struct AnchorPath *APath;
  151.      struct TestData tdat;
  152.      ULONG retval;
  153.  
  154.      tdat.password = args.password;
  155.      tdat.test = args.test;
  156.      tdat.all = args.all;
  157.      tdat.save = args.save;
  158.      tdat.fib = fib;
  159.      if(args.logfile)
  160.        tdat.logfh = Open(args.logfile, MODE_READWRITE);
  161.      else
  162.        tdat.logfh = 0;
  163.  
  164.      if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath)+
  165.      PATHNAME_SIZE, MEMF_PUBLIC|MEMF_CLEAR)))
  166.      {
  167.       APath->ap_BreakBits = SIGBREAKF_CTRL_C;
  168.       APath->ap_Strlen = PATHNAME_SIZE;
  169.  
  170.       for(retval = MatchFirst(args.filename, APath); !retval; retval = MatchNext(APath))
  171.       {
  172.        if(APath->ap_Flags & APF_DIDDIR)
  173.         APath->ap_Flags &= ~APF_DIDDIR;
  174.        else if(APath->ap_Info.fib_DirEntryType > 0)
  175.        {
  176. /*        if(args.deep)
  177.          APath->ap_Flags |= APF_DODIR; */
  178.        }
  179.        else if((error = DoIt(APath->ap_Buf, &tdat, args.method)))
  180.          break;
  181.       }
  182.       MatchEnd(APath);
  183.       FreeMem(APath, sizeof(struct AnchorPath)+PATHNAME_SIZE);
  184.      }
  185.      if(tdat.logfh)
  186.        Close(tdat.logfh);
  187.  
  188.      FreeDosObject(DOS_FIB, fib);
  189.     }
  190.     FreeArgs(rda);
  191.    }
  192.    CloseLibrary(xpkbase);
  193.   }
  194.   if(error && IoErr()) /* print the error */
  195.    PrintFault(IoErr(), 0);
  196.   CloseLibrary((struct Library *) dosbase);
  197.  }
  198.  
  199.  return error;
  200. }
  201.  
  202. ULONG DoIt(STRPTR name, struct TestData *tdat, STRPTR *method)
  203. {
  204.   ULONG error = RETURN_FAIL;
  205.   BPTR fh;
  206.  
  207.   if((fh = Open(name, MODE_OLDFILE)))
  208.   {
  209.    if(ExamineFH(fh, tdat->fib))
  210.    {
  211.     tdat->sbufsize = tdat->fib->fib_Size;
  212.     tdat->ubufsize = tdat->fib->fib_Size + XPK_MARGIN;
  213.     tdat->pbufsize = tdat->fib->fib_Size + (tdat->fib->fib_Size>>5) + (XPK_MARGIN<<1);
  214.  
  215.     if((tdat->sbuf = (STRPTR) AllocMem(tdat->sbufsize, MEMF_ANY)))
  216.     {
  217.      if((tdat->ubuf = (STRPTR) AllocMem(tdat->ubufsize, MEMF_ANY|MEMF_CLEAR)))
  218.      {
  219.       if((tdat->pbuf = (STRPTR) AllocMem(tdat->pbufsize, MEMF_ANY)))
  220.       {
  221.        if(Read(fh, tdat->sbuf, tdat->sbufsize) == tdat->sbufsize)
  222.        {
  223.         struct timerequest timerequest = {0};
  224.  
  225.     if(tdat->test)
  226.     {
  227.       if((tdat->cbuf = (STRPTR) AllocMem(tdat->sbufsize, MEMF_ANY)))
  228.         CopyMem(tdat->sbuf, tdat->cbuf, tdat->sbufsize);
  229.     }
  230.     else
  231.       tdat->cbuf = 0;
  232.  
  233.         if(!OpenDevice("timer.device", UNIT_ECLOCK, (struct IORequest *)
  234.         &timerequest, 0))
  235.     {
  236.      TimerBase = timerequest.tr_node.io_Device;
  237.      if((tdat->pinfo = (struct XpkPackerInfo *)
  238.      XpkAllocObject(XPKOBJ_PACKERINFO, 0)))
  239.      {
  240.       if((tdat->minfo = (struct XpkMode *)
  241.       XpkAllocObject(XPKOBJ_MODE, 0)))
  242.       {
  243.            PrintTxt(tdat->logfh, HEADER, name, tdat->sbufsize);
  244.            if(method)
  245.            {
  246.             for(;*method && !CTRL_C; ++method)
  247.             {
  248.          if(!(*method)[0] || !(*method)[1] ||
  249.          !(*method)[2] || !(*method)[3])
  250.           PrintErr(tdat->logfh, XPKERR_MISSINGLIB, *method); 
  251.          else
  252.          {
  253.           (*method)[0] = toupper((*method)[0]);
  254.           (*method)[1] = toupper((*method)[1]);
  255.           (*method)[2] = toupper((*method)[2]);
  256.           (*method)[3] = toupper((*method)[3]);
  257.           if((*method)[4] == '.')
  258.               {
  259.                (*method)[4] = 0;
  260.                DoTest(tdat, *method, strtoul(*method+5, 0,10));
  261.               }
  262.               else
  263.                ScanMethods(tdat, *method);
  264.              }
  265.             }
  266.            }
  267.            else
  268.             ScanPackers(tdat);
  269.        error = 0;
  270.        XpkFreeObject(XPKOBJ_MODE, tdat->minfo);
  271.       }
  272.       XpkFreeObject(XPKOBJ_PACKERINFO, tdat->pinfo);
  273.      }
  274.      CloseDevice((struct IORequest *) &timerequest);
  275.      
  276.      if(tdat->cbuf)
  277.        FreeMem(tdat->cbuf, tdat->sbufsize);
  278.         }
  279.        }
  280.        FreeMem(tdat->pbuf, tdat->pbufsize);
  281.       }
  282.       FreeMem(tdat->ubuf, tdat->ubufsize);
  283.      }
  284.      FreeMem(tdat->sbuf, tdat->sbufsize);
  285.     }
  286.    }
  287.    Close(fh);
  288.   }
  289.   return error;
  290. }
  291.  
  292. /* These must be defined false, because this is a benchmark tool ! */
  293. static struct TagItem deftags[] = {
  294. { XPK_Preferences, FALSE},
  295. { XPK_UseXfdMaster, FALSE},
  296. { XPK_UseExternals, FALSE},
  297. { XPK_PassRequest, FALSE},
  298. { XPK_ChunkReport, FALSE},
  299. { TAG_DONE, 0},
  300. };
  301.  
  302. LONG GetPackData(struct BenchData *b, struct TestData *t, STRPTR pwd)
  303. {
  304.   struct EClockVal eval1, eval2;
  305.   LONG err, d;
  306.   ULONG freq;
  307.  
  308.   Forbid();
  309.   freq = ReadEClock(&eval1);
  310.   err = XpkPackTags(
  311.     XPK_InBuf,    t->sbuf,
  312.     XPK_InLen,    t->sbufsize,
  313.     XPK_OutBuf,    t->pbuf,
  314.     XPK_OutBufLen,    t->pbufsize,
  315.     XPK_GetOutLen,    &(b->CSize),
  316.     pwd ? XPK_Password : TAG_IGNORE,    pwd,
  317.     XPK_PackMethod,    b->method,
  318.     XPK_PackMode,    b->mode,
  319.     TAG_MORE,    deftags);
  320.   ReadEClock(&eval2);
  321.   Permit();
  322.   b->CTime = eval2.ev_lo - eval1.ev_lo;
  323.   if(err)
  324.     return err;
  325.   Forbid();
  326.   ReadEClock(&eval1);
  327.   err = XpkUnpackTags(
  328.     XPK_InBuf,    t->pbuf,
  329.     XPK_InLen,    t->pbufsize,
  330.     XPK_OutBuf,    t->ubuf,
  331.     XPK_OutBufLen,    t->ubufsize,
  332.     XPK_GetOutLen,    &d,
  333.     pwd ? XPK_Password : TAG_IGNORE, pwd,
  334.     TAG_MORE,    deftags);
  335.   ReadEClock(&eval2);
  336.   Permit();
  337.   if(err)
  338.     return err;
  339.   b->UTime = eval2.ev_lo - eval1.ev_lo;
  340.  
  341.   if(d != t->sbufsize)
  342.   {
  343.     PrintTxt(t->logfh, SIZEERR, b->method, t->sbufsize, t);
  344.     return 1;
  345.   }
  346.   if(t->test)
  347.   {
  348.     if(t->cbuf) /* check for destoyed source buffer */
  349.     {
  350.       for(; d && t->sbuf[d-1] == t->cbuf[d-1]; --d)
  351.         ;
  352.       if(d)
  353.       {
  354.         CopyMem(t->cbuf, t->sbuf, t->sbufsize); /* restore buffer */
  355.         memset(t->ubuf, 0, t->ubufsize);
  356.         VPrintTxt(t->logfh, SRCERR, &b->method);
  357.         return 1;
  358.       }
  359.     }
  360.  
  361.     for(d = t->sbufsize; d && t->sbuf[d-1] == t->ubuf[d-1]; --d)
  362.       ;
  363.     memset(t->ubuf, 0, t->ubufsize);
  364.     if(d)
  365.     {
  366.       VPrintTxt(t->logfh, BUFERR, &b->method);
  367.       return 1;
  368.     }
  369.   }
  370.  
  371.   if(t->save)
  372.   {
  373.     ULONG lock, fh;
  374.  
  375.     if((lock = Lock(t->save, SHARED_LOCK)))
  376.     {
  377.       lock = CurrentDir(lock);
  378.       if(Examine(lock, t->fib) && t->fib->fib_DirEntryType > 0)
  379.       {
  380.         UBYTE data[10];
  381.  
  382.         sprintf(data, "%.4s.%03ld", b->method, b->mode);
  383.         if((fh = Open(data, MODE_NEWFILE)))
  384.         {
  385.           Write(fh, t->pbuf, b->CSize);
  386.           Close(fh);
  387.         }
  388.       }
  389.       UnLock(CurrentDir(lock));
  390.     }
  391.   }
  392.  
  393.   if((d = 1000 - ((1000 * b->CSize)/t->sbufsize)) < 0)
  394.     d = 0;
  395.  
  396.   b->Rate   = d/10;
  397.   b->Rate10 = d % 10;
  398.  
  399.   b->CTime100 = (100 * (b->CTime % freq)) / freq;
  400.   b->UTime100 = (100 * (b->UTime % freq)) / freq;
  401.   b->CTime /= freq;
  402.   b->UTime /= freq;
  403.  
  404.   if(!b->CTime && !b->CTime100)
  405.     b->CTime100 = 1;
  406.   if(!b->UTime && !b->UTime100)
  407.     b->UTime100 = 1;
  408.  
  409.   b->CSpd = ((100*t->sbufsize) / ((100 * b->CTime) + b->CTime100));
  410.   b->USpd = ((100*t->sbufsize) / ((100 * b->UTime) + b->UTime100));
  411.   return 0;
  412. }
  413.  
  414. void DoTest(struct TestData *t, STRPTR method, ULONG mode)
  415. {
  416.   struct BenchData b;
  417.   struct Library *xbase;
  418.   UBYTE libname[] = "compressors/xpk____.library";
  419.  
  420.   LONG err;
  421.  
  422.   CopyMem(method, libname+15, 4);
  423.  
  424.   if(!(xbase = OpenLibrary(libname, 0)))
  425.   {
  426.     PrintErr(t->logfh, XPKERR_MISSINGLIB, method);
  427.     return;
  428.   }
  429.   b.version = xbase->lib_Version;
  430.   b.revision = xbase->lib_Revision;
  431.  
  432.   if(b.revision < 10)
  433.     b.pad = "   ";
  434.   else if(b.revision < 100)
  435.     b.pad = "  ";
  436.   else if(b.revision < 1000)
  437.     b.pad = " ";
  438.   else
  439.     b.pad = "";
  440.  
  441.   CloseLibrary(xbase);
  442.  
  443.   libname[19] = 0;
  444.   b.method = libname+15;
  445.   if((b.mode = mode) > 100)
  446.     b.mode = 100;
  447.  
  448.   if((err = XpkQueryTags(
  449.     XPK_PackerQuery,    t->pinfo,
  450.     XPK_PackMethod,        b.method,
  451.     TAG_MORE,        deftags,
  452.     TAG_DONE)))
  453.   {
  454.     PrintErr(t->logfh, err, b.method);
  455.     return;
  456.   }
  457.  
  458.   if((t->pinfo->xpi_Flags & XPKIF_NEEDPASSWD) && !t->password)
  459.     return;
  460.  
  461.   if((t->pinfo->xpi_Flags & XPKIF_ENCRYPTION) && t->password)
  462.   {
  463.     b.password = "*";
  464.     if((err = GetPackData(&b, t, t->password)))
  465.     {
  466.       if(err < 0)
  467.         PrintErr(t->logfh, err, b.method);
  468.       return;
  469.     }
  470.     else
  471.       VPrintTxt(t->logfh, DATATXT, &b);
  472.   }
  473.   if(!(t->pinfo->xpi_Flags & XPKIF_NEEDPASSWD))
  474.   {
  475.     b.password = " ";
  476.     if((err = GetPackData(&b, t, 0)))
  477.     {
  478.       if(err < 0)
  479.         PrintErr(t->logfh, err, b.method);
  480.       return;
  481.     }
  482.     else
  483.       VPrintTxt(t->logfh, DATATXT, &b);
  484.   }
  485. }
  486.  
  487. void ScanPackers(struct TestData *t)
  488. {
  489.   LONG err, i;
  490.   struct XpkPackerList *pl;
  491.  
  492.   if((pl = (struct XpkPackerList *) XpkAllocObject(XPKOBJ_PACKERLIST, 0)))
  493.   {
  494.     if((err = XpkQueryTags(
  495.     XPK_PackersQuery,    pl,
  496.     TAG_MORE,        deftags,
  497.     TAG_DONE)))
  498.     {
  499.       PrintErr(t->logfh, err, 0);
  500.       return;
  501.     }
  502.  
  503.     for(i = 0; i < pl->xpl_NumPackers && !CTRL_C; i++)
  504.       ScanMethods(t, pl->xpl_Packer[i]);
  505.  
  506.     XpkFreeObject(XPKOBJ_PACKERLIST, pl);
  507.   }
  508. }
  509.  
  510. void PrintTxt(BPTR logfh, STRPTR txt, ...)
  511. {
  512.   VPrintTxt(logfh, txt, (APTR) ((ULONG)&txt+sizeof(STRPTR)));
  513. }
  514.  
  515. void VPrintTxt(BPTR logfh, STRPTR txt, APTR args)
  516. {
  517.   VPrintf(txt, args);
  518.   if(logfh)
  519.     VFPrintf(logfh, txt, args);
  520. }
  521.  
  522. void PrintErr(BPTR logfh, ULONG err, STRPTR method)
  523. {
  524.   UBYTE errbuf[XPKERRMSGSIZE];
  525.       
  526.   XpkFault(err, method, errbuf, XPKERRMSGSIZE);
  527.   Printf("%s\n", errbuf);
  528.   if(logfh)
  529.     FPrintf(logfh, "%s\n", errbuf);
  530. }
  531.  
  532. void ScanMethods(struct TestData *t, STRPTR method)
  533. {
  534.   LONG err;
  535.   ULONG mode;
  536.  
  537.   if(t->all)
  538.   {
  539.     for(mode = 0; mode <= 100 && !CTRL_C; ++mode)
  540.      DoTest(t, method, mode);
  541.   }
  542.   else
  543.   {
  544.     for(mode = 0; mode < 100 && !CTRL_C; mode = t->minfo->xm_Upto + 1)
  545.     {
  546.       if((err = XpkQueryTags(
  547.     XPK_ModeQuery,    t->minfo,
  548.     XPK_PackMethod,    method,
  549.     XPK_PackMode,     mode,
  550.     TAG_MORE,    deftags)))
  551.       {
  552.         PrintErr(t->logfh, err, method);
  553.         return;
  554.       }
  555.       DoTest(t, method, t->minfo->xm_Upto);
  556.     }
  557.   }
  558. }
  559.  
  560.